#ifndef GAME_H
#define GAME_H

#include "Board.h"
#include <string>
#include <ctime>
#include <cstdlib>

class Game
{
public:
	static const int MAX_TURNS = 200;

	// TODO: Change Move and Attack to Enums.
	enum StringAction {
		MovePiece = 5,
		Attack = 6
	};
	enum GameDifficulty {
		Random = 1,
		Easy = 2,
		Medium = 3,
		Hard = 4
	};

	Game(void);

	Game(int columns, int rows);

	virtual ~Game(void);

	friend std::ostream& operator<<(std::ostream& os , Game& game); 

	/** \brief Handles console input
	Takes arguments.
	- make fcol frow tcol trow. Which makes the respective move if legal.
	- retract Undo's the last made move if any. does nothing if no prior moves.
	- level [random|easy|medium|hard] Changes difficult level.
		- Random, makes a random legal move.
		- Easy, makes a evalutated move, by making all possible moves, and chooses the highest evaluated move.
			defult evaluate is piece count. See docs on virtual int evaluate().
		- Medium, Not implemented yet.
		- Hard, Not implemented yet.
	*/
	bool update(std::stringstream &action);

	int currentPlayer(); /**< \brief Returns the id for player to make a turn. */


	/** \brief Returns the name of the game, defult = Generic Board Game
	*/
	std::string getName(){ return m_gameName; }

	/** \brief Move piece from field to another
	Move contains coordinates for from-col, from-row and to-col to-row 
	make move moves a piece respectively from gameMove if action is legal.
	gameMove stores the move in lastMoves vector, The string is constructed like so:
	<action> <coord> <coord> <player> (<gameSpecialAction> ...);
	<action	:: <Attack> ; Move ;
	<attack>:: Attack <player>
	<coord>	:: <int> <int>;
	<player>:: Player1; Player2;
	<int>	:: 1..n
	Function passes a stringstream to gameSpecialAction where the instruction
	string should be finished.
	and then passes the string to makeMove(stringstream &gameMove)
	*/
	void makeMove( const Move &gameMove );

	/** \brief Acts on gameMove string.
	Acts on string constructed with makeMove(const Move &)
	*/
	void makeMove( std::stringstream &gameMove);

	/**\brief Checks for move legality.
	Function checks if asked move is legal, base class handles cases wich 
	break the game state: Out of board, Unavailable field, or move with no change.
	This function calls the virtual function legalMove()
	*/
	bool checkLegal(const Move &gameMove);

	/** \brief Act on the parameter string.
	Parses the string parameter and acts on it.
	<action> <coord> <coord> <player> (<gameSpecialAction> ...);
	<action	:: <Attack> ; Move ;
	<attack>:: Attack <player>
	<coord>	:: <int> <int>;
	<player>:: Player1; Player2;
	<int>	:: 1..n
	Calls doGameSpecialAction() with remainder after <player>
	*/
	void doMakeMove( std::stringstream &actionStream );

	/** \brief Undos the last move.
	Undos the last move and pops it from the lastMoves vector.
	*/
	void undoLastMove();
	
	/** \brief Returns a vector of legal moves.
	@param[in] unique defult false, If parameter is set, you weill get a new allocated memory, and you must delete it, else the vector is handled by class.
	The moves are returned in string format, following the same BNF:
	<action> <coord> <coord> <player> (<gameSpecialAction> ...);
	<action	:: <Attack> ; Move ;
	<attack>:: Attack <player>
	<coord>	:: <int> <int>;
	<player>:: Player1; Player2;
	<int>	:: 1..n
	*/
	std::vector<std::string>* getLegalMoves( bool unique = false);
	
	/** \brief Evaluate game stats
	returns the game board evaluation, defult behaviour is piece count.
	0 = equal, Player2 -0+ Player1
	difference in piece count on table.
	*/
	virtual int evaluate();

	bool gameOver();

	int getPlayerPiecesCount(int player);/**< Returns the chosen player piece count. */
protected:
	Board& gameBoard() ; /**< Get a reference of the game board member */
	Debug* debugger; /**< Use for debugging messages if(debugger->debug()) error msg */
	bool AI; /**< Boolean toggle to disable console output while calculating legal moves. */
	int totalTurns; /**< Holds tabs on total moves made. */
	std::string m_gameName; /**< Returns the name of the game. */
	int columns();  /**< returns the number of columns */
	int rows();		/**< returns the number of rows */

private:
	Game( Game& ); /**< Disable copy constructor.*/ 
	Game& operator=(Game&);  /**< Disable assignment operator.*/ 
	
	/** \brief Initializes the game board.
	Calls virtual functions to initalize the board.
	*/
	void init();

	/** \brief GameSpecific win condition,
	Defult behaviour of game class, players with max piece count wins after MAX_TURNS.
	Is called after each makeMove.
	// TODO Disable MAX_TURNS
	*/
	virtual bool winCondition();

	/** \breif Get a list of destinations
	Returns a tuple list of possible destinations based on location.
	You should overwrite this with your game specific behaviour, this function
	should not handle illegal locations, since they will be filtered with
	checkLegal and legalMove functions.
	@param[in,out] possibleDestinations A vector of tuples, functions fills in this vector.
	@param[in] location const functions checks for legal moves from this location.
	*/
	virtual void getPossibleDestinations(std::vector<std::pair<int,int> > &possibleDestinations, std::pair<int,int> &location) = 0;

	/** \breif Initialize playes pieces.
	Override this function to place pieces logically on the table for each specific game.
	*/
	virtual void placePieces() = 0;	

	/** \brief Checks if move is legal.
	Is called by checkLegal and is checked prior to making changes to board.
	Legality handled by base class is as follows:
		- Out of board moves.
		- no move at all. (source == destination).
		- Unavailable field. 
	Override this for game specific legal moves. 
	*/
	virtual bool legalMove( const Move &gameMove ) = 0;
	
	/** \brief Constructs action string for game specific actions
	Add game specific logic here, actions made after moving piece.
	<action> <from> <to> <player> (<gameSpecialAction> if any)
	this string is used for acting on actions and undoing actions. 
	Later acted on with doGameSpecialAction
	@returns string Return a string with related action.
	*/
	virtual std::string gameSpecialAction(const Move &gameMove) = 0;

	/** \brief Act on the game specific action string
	Acts on the game specific action string constructed in gameSpecialAction.
	*/
	virtual void doGameSpecialAction(std::stringstream &actionStream, const Move &gameMove) = 0;

	/** \brief Undo game specific action.
	this function is called in the end of undoLastMove 
	and should be overridden if game has any special functionality.
	for defult you can just returns nothing.
	param[in,out] undoAction this parameter should be filled with game specific commands.
	param[in] actionStr The stringstream of te action to undo.
	*/
	virtual void undoSpecialAction(std::stringstream &undoAction, std::stringstream &actionStr) = 0;

	/** \brief Helper function to construct the Move String
	Follows this pattern, calls gameSpecialAction() to construct the
	game specific string.
	<action> <coord> <coord> <player> (<gameSpecialAction> ...);
	<action	:: <Attack> ; Move ;
	<attack>:: Attack <player>
	<coord>	:: <int> <int>;
	<player>:: Player1; Player2;
	<int>	:: 1..n
	*/
	void constructMoveString(const Move &gameMove, std::stringstream& stream );

	/** \brief Act AI with set difficulty
	*/
	void actAi();
	Board m_gameBoard; /**< The game board */

	int m_currentPlayer; /**< The player to make the next move*/
	int m_player1Pieces; /**< Player 1 piece count */
	int m_player2Pieces; /**< Player 2 piece count */
	
	int m_rows;
	int m_columns;

	/** \brief Stores the last n moves.
	Last moves stored on the format with space deliminaries
	Move from to movingPlayer gameSpecificAction ...
	<action> <coord> <coord> <player> (<gameSpecialAction> ...);
	<action	:: <Attack> ; Move ;
	<attack>:: Attack <player>
	<coord>	:: <int> <int>;
	<player>:: Player1; Player2;
	<int>	:: 1..n
	*/
	std::vector<std::string*> lastMoves;

	// TODO: Implement
	/** \brief Temp legal moves container.
	Holds legal moves for one turn.
	NEVER ACCESS DIRECTLY, ONLY THROUGH getLegalMoves().!!!
	*/
	std::vector<std::string>* contLegalMoves;
	bool legalMovesSet;

	/** \brief Game difficulty
	Diffuculty:
	random: Random legal move.
	easy:
	medium:
	hard:
	*/
	int m_difficulty;
	bool m_gameOver; /**< Toggles game over, when winCondition is met, this is toggled. see overwriting winCondition()*/

	bool m_gameRunning;
};

#endif //GAME_H

